import { isObject, isArray, isEmpty } from 'lodash-es';

export class ParamsFilter {
  static filter(data, config = { enable: true }) {
    if (!config.enable) return data;
    
    const rules = {
      removeEmpty: true,
      removeNull: true,
      removeUndefined: true,
      removeFalsy: false,
      ...config.rules
    };

    return ParamsFilter.#filterValue(data, rules);
  }

  static #filterValue(data, rules) {
    if (data === null || data === undefined) {
      return undefined;
    }

    if (isArray(data)) {
      return ParamsFilter.#filterArray(data, rules);
    }

    if (isObject(data)) {
      return ParamsFilter.#filterObject(data, rules);
    }

    return ParamsFilter.#filterPrimitive(data, rules);
  }

  static #filterObject(obj, rules) {
    const result = {};

    for (const [key, value] of Object.entries(obj)) {
      const filtered = ParamsFilter.#filterValue(value, rules);
      if (!ParamsFilter.#shouldRemove(filtered, rules)) {
        result[key] = filtered;
      }
    }

    return isEmpty(result) ? undefined : result;
  }

  static #filterArray(arr, rules) {
    const filtered = arr
      .map(item => ParamsFilter.#filterValue(item, rules))
      .filter(item => !ParamsFilter.#shouldRemove(item, rules));

    return filtered.length ? filtered : undefined;
  }

  static #filterPrimitive(value, rules) {
    if (ParamsFilter.#shouldRemove(value, rules)) {
      return undefined;
    }
    return value;
  }

  static #shouldRemove(value, rules) {
    if (rules.custom && rules.custom(value)) {
      return true;
    }

    if (value === undefined && rules.removeUndefined) {
      return true;
    }

    if (value === null && rules.removeNull) {
      return true;
    }

    if (value === '' && rules.removeEmpty) {
      return true;
    }

    if (rules.removeFalsy && !value) {
      return true;
    }

    return false;
  }
}